import directives from "./directives.js";
import { reactive, effect } from "./reactive.js";

export class ToyVue {
    constructor(options) {
        const observed = reactive(options.data);
        for (const d of Reflect.ownKeys(options.data)) {
            Object.defineProperty(this, d, {
                get() { return observed[d] },
                set(value) { observed[d] = value; }
            })
        }

        this.template = document.querySelector(options.el);

        for (const method of Reflect.ownKeys(options.methods)) {
            this[method] = options.methods[method].bind(this);
        }

        this.init();
    }

    init() {
        this.traversal(this.template);
    }

    /**
     * @param {Node | Element} node 
     */
    traversal(node) {
        if (node.nodeType == Node.TEXT_NODE) {
            const textNode = node;
            // {{}}
            const reg = /{{([\s\S]+)}}/;
            const matched = textNode.textContent.trim().match(reg);
            if (matched) {
                const variable = matched[1].trim();
                const rawText = textNode.textContent;
                effect(() => textNode.textContent = rawText.replace(matched[0], this[variable]));
            }
        }

        if (node.nodeType == Node.ELEMENT_NODE) {
            const elementNode = node;
            const attrs = elementNode.attributes;

            for (const attr of attrs) {
                directives.forEach(direct => direct(elementNode, attr, this))
            }
        }

        if (node.hasChildNodes()) {
            for (const child of node.childNodes) {
                this.traversal(child);
            }
        }
    }
}

